package com.awesome.network.call;

import com.awesome.network.OkHttpHelper;
import com.awesome.network.callback.Callback;
import com.awesome.network.callback.FailureRunnable;
import com.awesome.network.callback.SuccessRunnable;
import com.awesome.network.exception.NetworkUnavailableException;
import com.awesome.network.util.NetworkStateHelper;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import okhttp3.Call;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Author: JFangZ
 * Email:janezhang1901@163.com
 * Date: 2021/4/28 14:22
 * Description:Call impl for download request.
 */
public class DownloadCallImpl extends AbsCall<File> {
    private final File mFile;

    public DownloadCallImpl(Call call, File file) {
        super(call);
        mFile = file;
    }

    @Override
    public void enqueue(Callback<File> callback) {
        try {
            // Network unavailable,failure.
            if (!NetworkStateHelper.SINGLETON.isAvailable()) {
                callback.onFailure(new NetworkUnavailableException());
                return;
            }
        } catch (NullPointerException ignored) {
        }
        OkHttpHelper.SINGLETON.addCall(this);
        mCall.enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                mHandler.post(new FailureRunnable<>(callback, e));
                OkHttpHelper.SINGLETON.removeCall(DownloadCallImpl.this);
            }

            @Override
            public void onResponse(Call call, Response response) {
                OkHttpHelper.SINGLETON.removeCall(DownloadCallImpl.this);
                InputStream inputStream = null;
                try {
                    inputStream = response.body().byteStream();
                    RandomAccessFile randomAccessFile = new RandomAccessFile(mFile, "rwd");
                    randomAccessFile.seek(randomAccessFile.length());
                    byte[] bytes = new byte[1024 * 1024];
                    int len;
                    while ((len = inputStream.read(bytes)) != -1) {
                        randomAccessFile.write(bytes, 0, len);
                    }
                    mHandler.post(new SuccessRunnable<>(callback, mFile));
                } catch (Exception e) {
                    mHandler.post(new FailureRunnable<>(callback, e));
                } finally {
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
    }

    @Override
    public File execute() throws Exception {
        try {
            // Network unavailable,failure.
            if (!NetworkStateHelper.SINGLETON.isAvailable()) {
                throw new NetworkUnavailableException();
            }
        } catch (NullPointerException ignored) {
        }
        OkHttpHelper.SINGLETON.addCall(this);
        Response response = mCall.execute();
        OkHttpHelper.SINGLETON.removeCall(this);
        ResponseBody responseBody = response.body();
        InputStream inputStream = responseBody.byteStream();
        RandomAccessFile randomAccessFile = new RandomAccessFile(mFile, "rwd");
        randomAccessFile.seek(randomAccessFile.length());
        byte[] bytes = new byte[1024 * 1024];
        int len;
        while ((len = inputStream.read(bytes)) != -1) {
            randomAccessFile.write(bytes, 0, len);
        }
        return mFile;
    }

    @Override
    public <O> TransformCallImpl<File, O> transform(ResponseTransformer<File, O> responseTransformer) {
        return new TransformCallImpl<>(mCall, File.class, responseTransformer);
    }
}